package com.lantosec.hmrp.modules.workflow.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lantosec.hmrp.core.kit.PageVO;
import com.lantosec.hmrp.core.kit.Result;
import com.lantosec.hmrp.core.log.ControllerLog;
import com.lantosec.hmrp.core.log.LogType;
import com.lantosec.hmrp.core.mvc.BaseController;
import com.lantosec.hmrp.modules.sysdata.entity.SysDataProcess;
import com.lantosec.hmrp.modules.sysdata.entity.SysProcessPublicity;
import com.lantosec.hmrp.modules.sysdata.service.ISysDataProcessService;
import com.lantosec.hmrp.modules.sysdata.service.ISysDataProcessTaskService;
import com.lantosec.hmrp.modules.sysdata.service.ISysProcessNotifyService;
import com.lantosec.hmrp.modules.sysdata.service.ISysProcessPublicityService;
import com.lantosec.hmrp.modules.sysdata.vo.ProcessInstanceStatisticsVO;
import com.lantosec.hmrp.modules.sysdata.vo.SysDataProcessTaskVO;
import com.lantosec.hmrp.modules.sysdata.vo.SysProcessNotifyVO;
import com.lantosec.hmrp.modules.sysdata.vo.SysProcessPublicityVO;
import com.lantosec.hmrp.modules.workflow.enumeration.ProcessStatusEnum;
import com.lantosec.hmrp.modules.workflow.service.IWorkflowQueryService;
import com.lantosec.hmrp.modules.workflow.service.IWorkflowRuntimeService;
import com.lantosec.hmrp.modules.workflow.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j2;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 流程管理控制器
 *
 * @author lichaowei
 * @date 2020/4/24
 */
@Api(value = "流程管理控制器", tags = "流程管理控制器")
@RestController
@RequestMapping("/workflow/runtime/")
@Log4j2
public class WorkflowRuntimeController extends BaseController {

    @Autowired
    private IWorkflowRuntimeService runtimeService;

    @Autowired
    private IWorkflowQueryService queryService;

    @Autowired
    private ISysDataProcessService dataProcessService;

    @Autowired
    private ISysDataProcessTaskService sysDataProcessTaskService;

    @Autowired
    private ISysProcessNotifyService sysProcessNotifyService;

    @Autowired
    private ISysProcessPublicityService sysProcessPublicityService;
    /**
     * 查询流程任务信息
     */
    @GetMapping("get")
    @ApiOperation(value = "查询流程任务信息")
    public Result<ProcessInfoVO> get(@ApiParam(value = "查询对象", required = true) QueryProcessVO condition) {
        condition.setUserId(super.getUserId());
        return queryService.getProcessInfo(condition);
    }

    /**
     * 保存流程任务，包括启动流程和处理流程任务
     */
    @PostMapping("save")
    @ControllerLog(name = "工作流发起流程", type = LogType.add)
    @ApiOperation(value = "保存流程任务")
    public Result<Void> save(@ApiParam(value = "保存流程任务", required = true)@RequestBody SaveProcessTaskVO processTaskVO) {
        processTaskVO.setUserId(super.getUserId());
        return runtimeService.save(processTaskVO);
    }

    /**
     * 工作流保存流程表单临时数据，启动流程实例
     */
    @PostMapping("saveTempData")
    @ControllerLog(name = "工作流保存流程表单临时数据", type = LogType.add)
    @ApiOperation(value = "保存流程表单临时数据")
    public Result<FlowTaskVO> saveFormData(@ApiParam(value = "保存流程表单数据", required = true)@RequestBody SaveProcessTaskVO processTaskVO) {
        try {
            processTaskVO.setUserId(super.getUserId());
            FlowTaskVO taskVO = runtimeService.saveFormData(processTaskVO);
            return Result.ok(taskVO);
        } catch (Exception ex) {
            return Result.fail(ex.getMessage());
        }
    }

    /**
     * 作废流程
     */
    @DeleteMapping("delete")
    @ControllerLog(name = "工作流作废流程", type = LogType.delete)
    @ApiOperation(value = "作废流程")
    public Result<Void> delete(@ApiParam(value = "作废流程对象", required = true)@RequestBody DeleteProcessInstanceVO deleteVO) {
        deleteVO.setUserId(super.getUserId());
        return runtimeService.deleteProcessInstance(deleteVO);
    }

    /**
     * 回退流程
     */
    @PostMapping("back")
    @ControllerLog(name = "工作流回退流程", type = LogType.update)
    @ApiOperation(value = "回退流程")
    public Result<Void> back(@ApiParam(value = "回退流程对象", required = true)@RequestBody BackProcessInstanceVO backVO) {
        try {
            backVO.setUserId(super.getUserId());
            runtimeService.backTask(backVO);
            return Result.ok();
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 查询个人待办的任务
     */
    @GetMapping("queryPersonalTask")
    @ApiOperation(value = "查询个人的任务")
    public Result<Page<FlowTaskVO>> queryTodoTask(PageVO page) {
        String userId = super.getUserId();
        return queryService.queryTodoTask(page, userId);
    }
    /**
     * 查询个人参与的流程任务
     */
    @GetMapping("queryPartakeTask")
    @ApiOperation(value = "查询个人参与的流程任务")
    public Result<Page<FlowTaskVO>> queryPartakeTask(PageVO<FlowTaskVO> page) {
        String userId = super.getUserId();
        return Result.ok(sysDataProcessTaskService.queryPartakeTask(page,userId));

        //return queryService.queryHisTaskInstanceByUserId(page, userId);
    }

    /**
     * 查询个人发起的流程实例
     */
    @GetMapping("queryStartProcess")
    @ApiOperation(value = "查询个人发起的流程实例")
    public Result<Page<HisProcessInstanceVO>> queryStartProcess(PageVO page) {
        String userId = super.getUserId();
        return queryService.queryStartProInstanceByUserId(page, userId);
    }

    /**
     * 根据流程Id查询历史任务
     */
    @GetMapping("queryHisTask/{processInstanceId}")
    @ApiOperation(value = "查询流程历史活动")
    public Result<List<SysDataProcessTaskVO>> queryHisTask(@ApiParam(value = "流程实例Id", required = true) @PathVariable(name = "processInstanceId") String processInstanceId) {
        return queryService.queryHisTaskInstance(processInstanceId);
    }

    /**
     * 指派任务
     */
    @PostMapping("appoint")
    @ControllerLog(name = "工作流指派任务", type = LogType.update)
    @ApiOperation(value = "指派任务")
    public Result<Void> appoint(@ApiParam(value = "指派任务对象", required = true)@RequestBody HandleTaskVO appointTaskVO) {
        try {
            appointTaskVO.setUserId(super.getUserId());
            runtimeService.appointTask(appointTaskVO);
            return Result.ok();
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 转发任务
     */
    @PostMapping("transmit")
    @ControllerLog(name = "工作流转发任务", type = LogType.update)
    @ApiOperation(value = "转发任务")
    public Result<Void> transmit(@ApiParam(value = "转发任务对象", required = true)@RequestBody HandleTaskVO copyTaskVO) {
        try {
            copyTaskVO.setUserId(super.getUserId());
            runtimeService.transmitTask(copyTaskVO);
            return Result.ok();
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    @GetMapping("getProcessPng/{processInstanceId}")
    @ApiOperation(value = "根据流程实例查询流程图")
    @Deprecated
    public Result<String> getProcessPng(@ApiParam(value = "流程实例Id", required = true) @PathVariable(name = "processInstanceId") String processInstanceId) {
        try {
            return queryService.getProcessDiagram(processInstanceId, "");
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 根据流程定义Id查询流程图,图片以Base64形式返回
     * @param processDefinitionId   流程定义Id
     * @return
     */
    @GetMapping("getProcessPngByDefinitionId/{processDefinitionId}")
    @ApiOperation(value = "根据流程定义查询流程图")
    @Deprecated
    public Result<String> getProcessPngByDefinitionId(@ApiParam(value = "流程定义Id", required = true) @PathVariable(name = "processDefinitionId") String processDefinitionId) {
        try {
            return queryService.getProcessDiagram("", processDefinitionId);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    @GetMapping("getProcessImage/{processInstanceId}")
    @ApiOperation(value = "根据流程定义查询流程图信息")
    public Result<ProcessImageVO> getProcessImage(@ApiParam(value = "流程实例Id", required = true) @PathVariable(name = "processInstanceId") String processInstanceId) {
        try {
            return queryService.getProcessImage(processInstanceId, "");
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 根据流程定义Id查询流程图
     * @param processDefinitionId   流程定义Id
     * @return
     */
    @GetMapping("getProcessImageByDefinitionId/{processDefinitionId}")
    @ApiOperation(value = "根据流程定义查询流程图信息")
    public Result<ProcessImageVO> getProcessImageByDefinitionId(@ApiParam(value = "流程定义Id", required = true) @PathVariable(name = "processDefinitionId") String processDefinitionId) {
        try {
            return queryService.getProcessImage("", processDefinitionId);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 查询全部流程实例列表
     * @return
     */
    @GetMapping("queryAllProcessInstance")
    @ApiOperation(value = "查询全部流程实例列表")
    public Result<Page<SysDataProcess>> queryAllProcessInstance(@ApiParam(value = "分页对象", required = true) PageVO<SysDataProcess> page
            , @ApiParam(value = "搜索条件", required = true) SysDataProcessQueryVO condition) {
        try {
            Page<SysDataProcess> result = dataProcessService.queryProcessInstanceList(page, condition);
            return Result.ok(result);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 查询个人的流程知会列表
     */
    @GetMapping("queryNotifyProcess")
    //@ControllerLog(name = "查询个人的流程知会列表", type = LogType.select)
    @ApiOperation(value = "查询个人的流程知会列表")
    public Result<Page<SysProcessNotifyVO>> queryNotifyProcess(PageVO<SysProcessNotifyVO> page,
                                                       @ApiParam(value = "状态") @RequestParam(name = "notifyStatus",required = false) String notifyStatus) {
        String userId = super.getUserId();
        Page<SysProcessNotifyVO> list = sysProcessNotifyService.queryListByUserId(page, userId, notifyStatus);
        return Result.ok(list);
    }

    /**
     * 流程知会已读
     */
    @PostMapping("readProcessNotify")
    @ControllerLog(name = "流程知会已读状态修改", type = LogType.update)
    @ApiOperation(value = "流程知会已读")
    public Result<Boolean> readProcessNotify(@ApiParam(value = "流程实例Id", required = true)@RequestBody String processInstanceId) {
        String userId = super.getUserId();
        JSONObject jsonObject = JSON.parseObject(processInstanceId);
        boolean flag = sysProcessNotifyService.updateStatus(userId, jsonObject.get("processInstanceId").toString());
        return Result.ok(flag);
    }

    /**
     * 查询流程公示列表
     */
    @GetMapping("queryProcessPublicity")
    @ApiOperation(value = "查询流程公示列表")
    public Result<Page<SysProcessPublicityVO>> queryProcessPublicity(PageVO<SysProcessPublicity> page) {
        Page<SysProcessPublicityVO> list = sysProcessPublicityService.queryList(page);
        return Result.ok(list);
    }

    /**
     * 根据流程分类Id分组统计流程实例
     */
    @GetMapping("queryProcessStatistics")
    @ApiOperation(value = "根据流程分类Id分组统计流程实例")
    public Result<List<ProcessInstanceStatisticsVO>> queryProcessStatistics(SysDataProcessQueryVO condition) {
        List<ProcessInstanceStatisticsVO> list = dataProcessService.queryProcessInstanceStatistics(condition.getStartTime(), condition.getEndTime());
        return Result.ok(list);
    }

    /**
     * 查询待处理的流程数量
     */
    @GetMapping("queryTodoCount")
    @ApiOperation(value = "查询待处理的流程数量")
    public Result<ProcessCountVO> queryTodoCount() {
        ProcessCountVO countVO = new ProcessCountVO();
        String userId = super.getUserId();
        // 待办流程数量
        long todoCount = queryService.countTodoTask(userId);
        countVO.setTodoCount(todoCount);
        // 未读的转发通知数量
        long notifyCount = sysProcessNotifyService.countByUserId(userId);
        countVO.setNotifyCount(notifyCount);
        // 发起的流程数量
        long startCount = dataProcessService.countStartProcess(userId);
        countVO.setStartCount(startCount);
        // 参与的流程数量
        long partakeCount = sysDataProcessTaskService.countPartakeTask(userId);
        countVO.setPartakeCount(partakeCount);

        return Result.ok(countVO);
    }
}
